home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / procssng / ccs / ccs-11tl.lha / lbl / hips / sources / isobuild / server.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-11  |  18.4 KB  |  753 lines

  1. /*
  2.    server.c
  3. */
  4. /***********************************************************************/
  5. /************* routines for server version of isobuild  ****************/
  6. /***********************************************************************/
  7. /*
  8.  * for use with isoserv program:  written by David Robertson, LBL
  9.  *                    and  Brian Tierney, LBL
  10.  */
  11.  
  12. /* $Id: server.c,v 1.6 1992/01/31 02:05:45 tierney Exp $ */
  13.  
  14. /* $Log: server.c,v $
  15.  * Revision 1.6  1992/01/31  02:05:45  tierney
  16.  * *** empty log message ***
  17.  *
  18.  * Revision 1.5  1992/01/30  20:06:09  davidr
  19.  * before Brian's changes
  20.  *
  21.  * Revision 1.4  1992/01/10  01:59:31  davidr
  22.  * works with triserv now
  23.  *
  24.  * Revision 1.3  1992/01/07  23:15:43  davidr
  25.  * playing around with what to do with false
  26.  * surfaces
  27.  *
  28.  * Revision 1.2  1991/12/19  01:42:20  davidr
  29.  * added RCS identification markers
  30.  * */
  31.  
  32. static char rcsid[] = "$Id: server.c,v 1.6 1992/01/31 02:05:45 tierney Exp $";
  33.  
  34. #include "isobuild.h"
  35. #include "server.h"
  36.  
  37. #include <sys/socket.h>
  38. #include <netinet/in.h>
  39. #include <netdb.h>
  40. #include <sys/signal.h>
  41. #include <ctype.h>
  42.  
  43. struct movie_control {
  44.     int       num_frames;
  45.     float     TVAL[2];
  46.     float     d_TVAL;
  47.     int       SX[2];
  48.     int       SY[2];
  49.     int       SZ[2];
  50.     int       EX[2];
  51.     int       EY[2];
  52.     int       EZ[2];
  53.     float     d_SX;
  54.     float     d_SY;
  55.     float     d_SZ;
  56.     float     d_EX;
  57.     float     d_EY;
  58.     float     d_EZ;
  59. };
  60.  
  61. struct movie_control movie;
  62.  
  63. char      render_host[80];
  64. int       render_portnum;
  65. int       render_sock;
  66. int       ui_sock;
  67. int       render_start = 1;
  68.  
  69. int       tessel_param_changed;
  70.  
  71. /***********************************************************************/
  72.  
  73. surfserv()
  74. {
  75.     int       sock;
  76.     struct sockaddr_in server;
  77.     char      proc_num;
  78.     int       rval;
  79.     FILE     *fp = NULL;
  80.     FILE     *open_surf_file(), *gen_highres();
  81.     void      catch_sigs();
  82.  
  83.  
  84.     catch_sigs();        /* catch main interrupts to send msg to
  85.                  * client */
  86.  
  87.  
  88.     /* create socket  */
  89.     sock = socket(AF_INET, SOCK_STREAM, 0);
  90.     if (sock < 0) {
  91.     perror("opening stream socket");
  92.     exit(1);
  93.     }
  94.     /* name socket using wildcards */
  95.     server.sin_family = AF_INET;
  96.     server.sin_addr.s_addr = INADDR_ANY;
  97.     server.sin_port = ntohs(PORT_NUM);
  98.     setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) 0, 0);
  99.     if (bind(sock, (char *) &server, sizeof(server))) {
  100.     perror("binding stream socket");
  101.     exit(1);
  102.     }
  103.     printf("socket has port #%d\n", ntohs(server.sin_port));
  104.  
  105.     /* Start accepting connections */
  106.     listen(sock, 5);
  107.     do {
  108.     ui_sock = accept(sock, 0, 0);
  109.     if (ui_sock == -1)
  110.         perror("accept");
  111.     else
  112.         do {
  113.         if ((rval = read(ui_sock, &proc_num, sizeof(char))) < 0) {
  114.             Status("NULLPROC read failure");
  115.         }
  116. #ifdef SERVER_DEBUG
  117.         Status("Contact from the client");
  118. #endif
  119.  
  120.         if (rval > 0) {
  121.             if (proc_num == FILEPROC)
  122.             fp = open_surf_file();
  123.             else if (proc_num == PARAMPROC && fp != NULL)
  124.             gen_update();
  125.             else if (proc_num == MOVIEPROC && fp != NULL)
  126.             gen_movie();
  127.             else if (proc_num == HIGHRESPROC && fp != NULL)
  128.             fp = gen_highres();
  129.         }
  130.         } while (rval != 0);
  131.     if (fp != NULL)
  132.         fclose(fp);
  133.     fp = NULL;
  134.     close(ui_sock);
  135.     close(render_sock);
  136.     render_start = 1;
  137.     } while (TRUE);
  138.     /* need to kill this process to stop it */
  139. }
  140.  
  141.  
  142. /************************************************************************/
  143.  
  144. gen_update()
  145. {
  146.     int       inbuf[PARAM_READ_LENGTH], tval;
  147.     void      tessellate_volume(), tessellate_blocks();
  148.  
  149. #ifdef SERVER_DEBUG
  150.     Status(" in gen_update.");
  151. #endif
  152.  
  153.     read(ui_sock, inbuf, PARAM_READ_LENGTH * SUNINT);
  154.     SEG_METHOD = inbuf[0];
  155.     tval = (Data_type) inbuf[1];
  156.     SX = inbuf[2];
  157.     SY = inbuf[3];
  158.     SZ = inbuf[4];
  159.     EX = inbuf[5];
  160.     EY = inbuf[6];
  161.     EZ = inbuf[7];
  162.     tessel_param_changed = inbuf[11];
  163.     if (inbuf[13] == 0)
  164.     DIVIDING = 1;
  165.     else
  166.     MARCH_NORMALS = inbuf[13] - 1;
  167.  
  168.     TVAL = tval * (data_max - data_min) / 255.;
  169.  
  170. #ifdef SERVER_DEBUG
  171.     fprintf(stderr, " recieved the following settings: \n");
  172.     fprintf(stderr, " SX: %d, SY: %d, SZ: %d, EX: %d, EY: %d, EZ: %d \n",
  173.         SX, SY, SZ, EX, EY, EZ);
  174.     fprintf(stderr, "threshold value: %d , scaled: %.2f \n", tval, (float) TVAL);
  175.     fprintf(stderr, "segment: %d \n", SEG_METHOD);
  176. #endif
  177.  
  178.     if (IN_MASK_FNAME != NULL && !DIVIDING)
  179.     SEG_METHOD = 4;
  180.  
  181.     if (SEG_METHOD > 1 && SKIP_BLOCKS)
  182. /*
  183.  * Can't use skip-block option with flood fill segmentation
  184.  */
  185.     SKIP_BLOCKS = 0;
  186.  
  187.     if (SKIP_BLOCKS)
  188.     tessellate_blocks();
  189.     else
  190.     tessellate_volume();
  191.  
  192. }
  193.  
  194. /*******************************************************************/
  195. FILE     *
  196. open_surf_file()
  197. {
  198.     char      s_infile[80];
  199.     FILE     *in_fp, *open_data_file();
  200.     int       rval, msg, len, size;
  201.     int       buf[FILEPROC_READ_LENGTH];
  202.     void      alloc_data_arrays(), compute_normal_array(), get_max_min();
  203.     int       hostlen;
  204.  
  205. #ifdef SERVER_DEBUG
  206.     fprintf(stderr, " in open_surf_file: \n");
  207. #endif
  208.  
  209.     rval = read(ui_sock, buf, FILEPROC_READ_LENGTH * SUNINT);
  210. #ifdef SERVER_DEBUG
  211.     fprintf(stderr, "read %d bytes \n", rval);
  212. #endif
  213.     if (rval == 0) {
  214.     Error("problem reading from socket.");
  215.     }
  216.     len = buf[0];
  217.     hostlen = buf[1];
  218.     strncpy(s_infile, (char *) (buf + 2), len);
  219.     strncpy(render_host, (char *) (buf + 22), hostlen);
  220.     /* KLUDGE:  change! */
  221.     render_portnum = buf[43] + 10000;
  222.  
  223.     s_infile[len] = '\0';
  224.  
  225.     render_host[hostlen] = '\0';
  226.  
  227.     if ((in_fp = open_data_file(s_infile)) == NULL)
  228.     return (in_fp);
  229.  
  230.     alloc_data_arrays(xdim, ydim, zdim);
  231.  
  232.     /* read in entire data set */
  233.     size = xdim * ydim * zdim;
  234.     if (read_hips_data(in_fp, data, size) < 0)
  235.     return (NULL);
  236.  
  237.     if (IN_MASK_FNAME != NULL && !DIVIDING) {
  238.     /* read in mask data */
  239.     if (read_mask_file(size) < 0)
  240.         return (NULL);
  241.     }
  242.     if (SKIP_BLOCKS)
  243.     num_blocks = block_setup();
  244.     else {
  245.     /* find minimum and maximum values in the file */
  246.     get_max_min(size, &data_max, &data_min);
  247.     if (VERBOSE)
  248.         fprintf(stderr, "Minimum data value: %.1f, Maximum data value: %.1f \n",
  249.             (float) data_min, (float) data_max);
  250.     }
  251.  
  252.     if (PRE_NORMALS)        /* compute normals for entire data set */
  253.     compute_normal_array();
  254.  
  255.  
  256. #ifdef SERVER_DEBUG
  257.     fprintf(stderr, " sending initial header \n");
  258. #endif
  259.  
  260.     msg = 1;
  261.     buf[0] = msg;
  262.     buf[1] = xdim;
  263.     buf[2] = ydim;
  264.     buf[3] = zdim;
  265.  
  266.  
  267.     write(ui_sock, buf, FILEPROC_WRITE_LENGTH * SUNINT);
  268.  
  269.     return (in_fp);
  270. }
  271.  
  272. /**************************************************************/
  273. FILE     *
  274. open_data_file(s_infile)
  275.     char     *s_infile;
  276. {
  277.     FILE     *in_fp = NULL;
  278.     char      old_infile[80];
  279.     int       msg;
  280.     int       buf[4];
  281.  
  282.     if (strcmp(s_infile, old_infile) == 0) {
  283.     fprintf(stderr, "file already loaded %s\n", s_infile);
  284.     msg = 0;
  285.     buf[0] = buf[1] = buf[2] = buf[3] = msg;
  286.     write(ui_sock, buf, FILEPROC_WRITE_LENGTH * SUNINT);
  287.     return (in_fp);
  288.     }
  289. #ifdef SERVER_DEBUG
  290.     fprintf(stderr, "trying to open %s \n", s_infile);
  291. #endif
  292.  
  293.     in_fp = fopen(s_infile, "r");
  294.     if (in_fp == NULL) {
  295.     fprintf(stderr, "no such data file %s\n", s_infile);
  296.     msg = 0;
  297.     buf[0] = buf[1] = buf[2] = buf[3] = msg;
  298.     write(ui_sock, buf, FILEPROC_WRITE_LENGTH * SUNINT);
  299. #ifdef SERVER_DEBUG
  300.     fprintf(stderr, "error message sent to client: %d \n", buf[0]);
  301. #endif
  302.     return (in_fp);
  303.     }
  304.     IN_FNAME = s_infile;    /* set global */
  305. #ifdef DEBUG
  306.     fprintf(stderr, "opening file %s \n", IN_FNAME);
  307. #endif
  308.  
  309.     if (get_size(in_fp) < 0)
  310.     return (NULL);
  311.  
  312.     return (in_fp);
  313. }
  314.  
  315. /*******************************************************************/
  316. void
  317. alloc_data_arrays(xsize, ysize, zsize)
  318.     int       xsize, ysize, zsize;
  319. {
  320.     static int old_xdim = 0, old_ydim = 0, old_zdim = 0;
  321.     Grid_type ***alloc_3d_grid_array();
  322.     Data_type ***alloc_3d_data_array();
  323.     CUBE_TRIANGLES **alloc_2d_cube_array();
  324.     FLOAT_VECT **alloc_2d_vector_array();
  325.     NORMAL_VECT ***alloc_3d_normal_array();
  326.  
  327.     if (xsize != old_xdim || ysize != old_ydim || zsize != old_zdim) {
  328.     BLOCK_SIZE = 0;        /* force block_size recomputation */
  329.  
  330.     if (grid != NULL) {
  331.         free_3d_grid_array(grid);
  332.         grid = NULL;
  333.     }
  334.     if (data != NULL) {
  335.         free_3d_data_array(data);
  336.         data = NULL;
  337.     }
  338.     if (normals != NULL) {
  339.         free_3d_normal_array(normals);
  340.         normals = NULL;
  341.     }
  342.     if (block_info_array != NULL) {
  343.         free_block_info_array(block_info_array);
  344.         block_info_array = NULL;
  345.     }
  346.     if (prevslice != NULL) {
  347.         free_2d_cube_array(prevslice);
  348.         prevslice = NULL;
  349.     }
  350.     if (currslice != NULL) {
  351.         free_2d_cube_array(currslice);
  352.         currslice = NULL;
  353.     }
  354.     if (gradient_curr_slice != NULL) {
  355.         free_2d_vector_array(gradient_curr_slice);
  356.         gradient_curr_slice = NULL;
  357.     }
  358.     if (gradient_next_slice != NULL) {
  359.         free_2d_vector_array(gradient_next_slice);
  360.         gradient_next_slice = NULL;
  361.     }
  362.     } else
  363.     return;
  364.  
  365.     old_xdim = xsize;
  366.     old_ydim = ysize;
  367.     old_zdim = zsize;
  368.  
  369.     if (grid == NULL)
  370.     grid = alloc_3d_grid_array(zsize, ysize, xsize);
  371.  
  372.     if (data == NULL)
  373.     data = alloc_3d_data_array(zsize, ysize, xsize);
  374.  
  375.     if (PRE_NORMALS && normals == NULL)
  376.     normals = alloc_3d_normal_array(zsize, ysize, xsize);
  377.  
  378.     if (DUP_CHECK && prevslice == NULL) {    /* for checking for dup verts */
  379.     prevslice = alloc_2d_cube_array(ysize, xsize);
  380.     currslice = alloc_2d_cube_array(ysize, xsize);
  381.     }
  382.     if (DIVIDING && DO_CUBE_CENTER_NORMALS) {
  383.     gradient_curr_slice = alloc_2d_vector_array(ydim, xdim);
  384.     gradient_next_slice = alloc_2d_vector_array(ydim, xdim);
  385.     }
  386.     return;
  387. }
  388.  
  389. /************************************************************************/
  390.  
  391. gen_movie()
  392. {
  393.     int       inbuf[MOVIE_READ_LENGTH];
  394.     void      tessellate_volume(), tessellate_blocks(), get_increments();
  395.     int       i;
  396.     float     tval;
  397.  
  398. #ifdef SERVER_DEBUG
  399.     fprintf(stderr, " in gen_movie: \n");
  400. #endif
  401.  
  402.     read(ui_sock, inbuf, MOVIE_READ_LENGTH * SUNINT);
  403.  
  404.     movie.num_frames = inbuf[1];
  405.     SEG_METHOD = inbuf[2];
  406.     movie.TVAL[0] = (Data_type) inbuf[3];
  407.     movie.TVAL[1] = (Data_type) inbuf[4];
  408.     movie.SX[0] = inbuf[5];
  409.     movie.SX[1] = inbuf[6];
  410.     movie.SY[0] = inbuf[7];
  411.     movie.SY[1] = inbuf[8];
  412.     movie.SZ[0] = inbuf[9];
  413.     movie.SZ[1] = inbuf[10];
  414.     movie.EX[0] = inbuf[11];
  415.     movie.EX[1] = inbuf[12];
  416.     movie.EY[0] = inbuf[13];
  417.     movie.EY[1] = inbuf[14];
  418.     movie.EZ[0] = inbuf[15];
  419.     movie.EZ[1] = inbuf[16];
  420.     /* CHANGE:  need MARCH_NORMALS */
  421.  
  422.  
  423. #ifdef SERVER_DEBUG
  424.     fprintf(stderr, " recieved the following movie settings: \n");
  425.     fprintf(stderr, "threshold start: %d, end: %d \n",
  426.         movie.TVAL[0], movie.TVAL[1]);
  427.     fprintf(stderr, "segment: %d  num_frames: %d\n",
  428.         SEG_METHOD, movie.num_frames);
  429. #endif
  430.  
  431.     get_increments();
  432.  
  433.     if (!tessel_param_changed)
  434.     movie.num_frames = 1;
  435.     for (i = 0; i <= movie.num_frames; i++) {
  436.     tval = movie.TVAL[0] + (movie.d_TVAL * (float) i);
  437.     TVAL = tval * (data_max - data_min) / 255.;
  438.     SX = movie.SX[0] + (int) (movie.d_SX * i);
  439.     SY = movie.SY[0] + (int) (movie.d_SY * i);
  440.     SZ = movie.SZ[0] + (int) (movie.d_SZ * i);
  441.     EX = movie.EX[0] + (int) (movie.d_EX * i);
  442.     EY = movie.EY[0] + (int) (movie.d_EY * i);
  443.     EZ = movie.EZ[0] + (int) (movie.d_EZ * i);
  444.  
  445. #ifdef SERVER_DEBUG
  446.     fprintf(stderr, "calling tessellate_volume with the following args: \n");
  447.     fprintf(stderr, " SX: %d, SY: %d, SZ: %d, EX: %d, EY: %d, EZ: %d \n",
  448.         SX, SY, SZ, EX, EY, EZ);
  449. #endif
  450.  
  451.     if (SEG_METHOD > 0 && SKIP_BLOCKS)
  452. /*
  453.  * Can't use skip-block option with flood fill segmentation
  454.  */
  455.         SKIP_BLOCKS = 0;
  456.  
  457.     if (SKIP_BLOCKS)
  458.         tessellate_blocks();
  459.     else
  460.         tessellate_volume();
  461.  
  462.     }
  463. }
  464.  
  465. /********************************************************/
  466. void
  467. get_increments()
  468. {
  469.  
  470.     if (movie.num_frames >= 2) {
  471.     movie.d_TVAL = ((float) (movie.TVAL[1] - movie.TVAL[0]) /
  472.             (float) (movie.num_frames));
  473.     movie.d_SX = ((float) (movie.SX[1] - movie.SX[0]) /
  474.               (float) (movie.num_frames));
  475.     movie.d_SY = ((float) (movie.SY[1] - movie.SY[0]) /
  476.               (float) (movie.num_frames));
  477.     movie.d_SZ = ((float) (movie.SZ[1] - movie.SZ[0]) /
  478.               (float) (movie.num_frames));
  479.     movie.d_EX = ((float) (movie.EX[1] - movie.EX[0]) /
  480.               (float) (movie.num_frames));
  481.     movie.d_EY = ((float) (movie.EY[1] - movie.EY[0]) /
  482.               (float) (movie.num_frames));
  483.     movie.d_EZ = ((float) (movie.EZ[1] - movie.EZ[0]) /
  484.               (float) (movie.num_frames));
  485.     }
  486.     return;
  487. }
  488.  
  489. /********************************************************/
  490. FILE     *
  491. gen_highres()
  492. {
  493.     /* not yet implemented !! */
  494.     return (NULL);
  495. }
  496.  
  497. /********************************************************/
  498. /* connect to rendering server */
  499.  
  500. connect_to_renderer(r_host, r_portnum)
  501.     char     *r_host;        /* symbolic or Internet dot host name of
  502.                  * server */
  503.     int       r_portnum;    /* port number */
  504. {
  505.     struct sockaddr_in r_server;
  506.     struct hostent *hp, *gethostbyname();
  507.     int       is_int_addr;    /* is in Internet address form */
  508.     unsigned long internet_addr;/* Internet address */
  509.  
  510.  
  511.     /* check whether symbolic name or Internet address */
  512.     check_host_type(r_host, &is_int_addr, &internet_addr);
  513.     /* if "dotted" Internet address */
  514.     if (is_int_addr)
  515.     r_server.sin_addr.s_addr = internet_addr;
  516.     else {            /* symbolic name */
  517.     if ((hp = gethostbyname(r_host)) == NULL) {
  518.         fprintf(stderr, "can't find server address '%s'\n", r_host);
  519.         exit(0);
  520.     }
  521.     memcpy((caddr_t) & r_server.sin_addr, hp->h_addr, hp->h_length);
  522.     }
  523.  
  524.     /* create socket */
  525.     render_sock = socket(AF_INET, SOCK_STREAM, 0);
  526.     if (render_sock < 0) {
  527.     perror("opening stream renderer socket");
  528.     exit(1);
  529.     }
  530.     fprintf(stderr, "Connecting to host %s at port %d, render socket # %d \n",
  531.         r_host, r_portnum, render_sock);
  532.  
  533.     /* connect socket using name specified by command line. */
  534.     r_server.sin_family = AF_INET;
  535.     r_server.sin_port = htons(r_portnum);
  536.  
  537.     /* establish connection */
  538.     if (connect(render_sock, &r_server, sizeof(r_server)) < 0) {
  539.     perror("connecting stream renderer socket");
  540.     exit(1);
  541.     }
  542. }
  543.  
  544. /********************************************************/
  545.  
  546. check_host_type(host, inter_addr, coded)
  547.     char     *host;        /* reference to server */
  548.     int      *inter_addr;    /* Internet address or not */
  549.     unsigned long *coded;    /* Internet address */
  550.  
  551. {
  552.     int       i;
  553.     int       j = 0;
  554.     int       parse_ptr = 0;
  555.     char      parse_addr[4][5];
  556.     int       temp_int;
  557.  
  558.     *coded = 0;
  559.     *inter_addr = 0;
  560.     /* see if contains 4 numbers and 3 periods */
  561.     for (i = 0; i < strlen(host); i++) {
  562.     if (host[i] == '.') {
  563.         if (j == 0) {
  564.         *inter_addr = 0;
  565.         break;
  566.         } else {
  567.         parse_addr[parse_ptr][j] = '\0';
  568.         j = 0;
  569.         ++parse_ptr;
  570.         if (parse_ptr > 3) {
  571.             *inter_addr = 0;
  572.             break;
  573.         }
  574.         }
  575.     } else if (j < 3) {
  576.         if (!isdigit(host[i])) {
  577.         *inter_addr = 0;
  578.         break;
  579.         }
  580.         parse_addr[parse_ptr][j++] = host[i];
  581.         *inter_addr = 1;
  582.     } else {
  583.         *inter_addr = 0;
  584.         break;
  585.     }
  586.     }
  587.     if (*inter_addr && (parse_ptr == 3)) {
  588.     parse_addr[3][j] = '\0';
  589.     if ((temp_int = atoi(parse_addr[0])) > 255)
  590.         *inter_addr = 0;
  591.     else {
  592.         *coded = (unsigned char) temp_int;
  593.         /* convert to long form */
  594.         for (i = 1; i < 4; i++) {
  595.         *coded << = 8;
  596.         if ((temp_int = atoi(parse_addr[i])) > 255) {
  597.             *inter_addr = 0;
  598.             break;
  599.         } else
  600.             *coded |= (unsigned char) temp_int;
  601.         }
  602.     }
  603.     }
  604. }
  605.  
  606. /********************************************************/
  607. void
  608. write_points_to_socket(plist, npoints, more)
  609.     POINT_PTR plist;
  610.     int       npoints, more;
  611. {
  612.     int       write_size;
  613.     int       buf[2];        /* header output buffer */
  614.     static int tot_points = 0;
  615.     int       num_written, total_to_send;
  616.     char     *out_ptr;
  617.  
  618.     if (render_start) {
  619.     connect_to_renderer(render_host, render_portnum);
  620.     render_start = 0;
  621.     }
  622.     tot_points += npoints;
  623.     if (!more) {
  624.     fprintf(stderr, "Writing %d points.\n", tot_points);
  625.     tot_points = 0;
  626.     }
  627.     buf[0] = more;
  628.     buf[1] = npoints;
  629.     write(render_sock, buf, 2 * sizeof(int));
  630.  
  631.     write_size = npoints * sizeof(POINT);
  632.  
  633.     total_to_send = write_size;
  634.     out_ptr = (char *) plist;
  635.  
  636.     while (total_to_send > 0) {
  637.     num_written = write(render_sock, out_ptr, total_to_send);
  638.     total_to_send -= num_written;
  639.     if (total_to_send > 0)
  640.         out_ptr += num_written;
  641.     }
  642. }
  643.  
  644. /********************************************************/
  645. void
  646. write_polys_to_socket(vertex_list, norm_list, conn_list, nverts, nconn, more)
  647.     VERT_PTR  vertex_list;
  648.     NORM_PTR  norm_list;
  649.     int      *conn_list;
  650.     int       nverts, nconn, more;
  651. {
  652.     int       write_size;
  653.     int       buf[4];        /* header output buffer */
  654.     static int tot_verts = 0;
  655.     int       num_written, total_to_send;
  656.     char     *out_ptr;
  657.     int       i, j;
  658.  
  659.     if (render_start) {
  660.     connect_to_renderer(render_host, render_portnum);
  661.     render_start = 0;
  662.     }
  663.     tot_verts += nverts;
  664.     if (!more) {
  665.     fprintf(stderr, "Writing %d vertices.\n", tot_verts);
  666.     tot_verts = 0;
  667.     }
  668. /* #define SDEBUG */
  669. #ifdef SDEBUG
  670.     fprintf(stderr, "\nWriting header to socket: %d nverts, %d nconn, %d more \n",
  671.         nverts, nconn, more);
  672.  
  673.     for (i = 0; i < 10; i++) {
  674.     fprintf(stderr, "vertex %d: %f,%f,%f \n",
  675.         i, vertex_list[i].x, vertex_list[i].y, vertex_list[i].z);
  676.     }
  677.     if (nconn > 0) {
  678.     j = 0;
  679.     for (i = 0; i < 10; i++) {
  680.         fprintf(stderr, "\nedge %d: %d,%d,%d \n", i,
  681.             conn_list[j++], conn_list[j++], conn_list[j++]);
  682.     }
  683.     }
  684. #endif
  685.  
  686.     buf[0] = more;
  687.     buf[1] = nverts;
  688.     buf[2] = nconn;
  689.     if (MARCH_NORMALS)
  690.     buf[3] = 1;
  691.     else
  692.     buf[3] = 0;
  693.     write(render_sock, buf, 4 * sizeof(int));
  694.  
  695.     /* write all vertices */
  696.     write_size = nverts * sizeof(VERTEX);
  697.  
  698.     total_to_send = write_size;
  699.     out_ptr = (char *) vertex_list;
  700.  
  701.     while (total_to_send > 0) {
  702.     num_written = write(render_sock, out_ptr, total_to_send);
  703.     total_to_send -= num_written;
  704.     if (total_to_send > 0)
  705.         out_ptr += num_written;
  706.     }
  707.  
  708.     if (MARCH_NORMALS) {
  709.     write_size = nverts * sizeof(NORMAL);
  710.  
  711.     total_to_send = write_size;
  712.     out_ptr = (char *) norm_list;
  713.  
  714.     while (total_to_send > 0) {
  715.         num_written = write(render_sock, out_ptr, total_to_send);
  716.         total_to_send -= num_written;
  717.         if (total_to_send > 0)
  718.         out_ptr += num_written;
  719.     }
  720.     }
  721.     if (nconn > 0) {
  722.     /* write edge list */
  723.     write_size = nconn * sizeof(int);
  724.     total_to_send = write_size;
  725.     out_ptr = (char *) conn_list;
  726.  
  727.     while (total_to_send > 0) {
  728.         num_written = write(render_sock, out_ptr, total_to_send);
  729.         total_to_send -= num_written;
  730.         if (total_to_send > 0)
  731.         out_ptr += num_written;
  732.     }
  733.     }
  734. }
  735.  
  736. /********************************************************/
  737.  
  738. void
  739. catch_sigs()
  740. {
  741.     void      exit_handler();
  742.  
  743.     signal(SIGHUP, exit_handler);
  744.     signal(SIGQUIT, exit_handler);
  745.     signal(SIGINT, exit_handler);
  746. /*
  747.     signal(SIGBUS, exit_handler);
  748.     signal(SIGSEGV, exit_handler);
  749.     signal(SIGFPE, exit_handler);
  750. */
  751.     signal(SIGILL, exit_handler);
  752. }
  753.